package org.onionframework.faces.extension;

import java.util.HashMap;
import java.util.Map;

import org.onionframework.core.Onion;

/**
 * A namespace for components
 * 
 * @author allan
 * 
 */
public class Namespace {
	
	public static final Namespace rootNamespace = new Namespace(null);

	private String name;
	private Map<String, Namespace> children = new HashMap<String, Namespace>();

	public Namespace(String name) {
		this.name = name;
	}

	/**
	 * Get a component or child namespace
	 */
	public Object get(String key) {
		Object component = getComponentInstance(qualifyName(key));
		return component == null ? children.get(key) : component;
	}

	public Namespace getChild(String key) {
		return children.get(key);
	}

	public Namespace getOrCreateChild(String key) {
		Namespace result = getChild(key);
		if (result == null) {
			result = new Namespace(qualifyName(key) + '.');
			addChild(key, result);
		}
		return result;
	}

	public Object getComponentInstance(String key) {
		if(Onion.getApplicationContext().containsBean(key))
			return Onion.getBean(key);
		else
			return null;
	}

	private String qualifyName(String key) {
		return name == null ? key : name + key;
	}

	public boolean hasChild(String key) {
		return children.containsKey(key);
	}

	public void addChild(String name, Namespace value) {
		children.put(name, value);
	}

	@Override
	public int hashCode() {
		return name == null ? 0 : name.hashCode();
	}

	@Override
	public boolean equals(Object other) {
		if (!(other instanceof Namespace)) {
			return false;
		} else {
			Namespace ns = (Namespace) other;
			return this.name == ns.name
					|| (this.name != null && this.name.equals(ns.name));
		}
	}

	@Override
	public String toString() {
		return "Namespace(" + (name == null ? "Root" : name) + ')';
	}

}
